#ifndef __GAPI_H
#define __GAPI_H

#include <config.h>
#include <systems.h>
#include <types.h>
#include <event.h>

/* create 16 bit 5/6/5 format pixel from RGB triplet */
#define RGB2PIXEL565(r, g, b)	((((r) & 0xf8) << 8) | (((g) & 0xfc) << 3) | (((b) & 0xf8) >> 3))

/* return 8 bit r, g or b component of 5/6/5 16 bit pixelval*/
#ifdef BGR
#define PIXEL565BLUE8(pixelval)        (((pixelval) >> 8) & 0xf8)
#define PIXEL565GREEN8(pixelval)       (((pixelval) >> 3) & 0xfc)
#define PIXEL565RED8(pixelval)         (((pixelval) << 3) & 0xf8)
#else
#define PIXEL565RED8(pixelval)         (((pixelval) >> 8) & 0xf8)
#define PIXEL565GREEN8(pixelval)       (((pixelval) >> 3) & 0xfc)
#define PIXEL565BLUE8(pixelval)        (((pixelval) << 3) & 0xf8)
#endif

#define RGB565TORGB888(pixelval) (PIXEL565RED8(pixelval) << 16 | PIXEL565GREEN8(pixelval) << 8 | PIXEL565BLUE8(pixelval))

/* YCbCr (YUV) to RGB macros */
#if defined(NIOS2_FPU_SUPPORT)
# define YUV2RGB_R(Y,CB,CR) FPU_ADD(Y, FPU_MUL(1.402, (float)(CR - 128)))
# define YUV2RGB_G(Y,CB,CR) FPU_SUB(Y, FPU_SUB(FPU_MUL(0.34414, (float)(CB - 128)), FPU_MUL(0.71414, (float)(CR - 128))))
# define YUV2RGB_B(Y,CB,CR) FPU_ADD(Y, FPU_MUL(1.772, (float)(CB - 128)))
#else
# define YUV2RGB_R(Y,CB,CR) (Y + 1.402 * (CR - 128))
# define YUV2RGB_G(Y,CB,CR) (Y - 0.34414 * (CB - 128) - 0.71414 * (CR - 128))
# define YUV2RGB_B(Y,CB,CR) (Y + 1.772 * (CB - 128))
#endif

#ifdef GPU_SUPPORT
typedef struct hw_dep_property {
    u8 command;
    u8 scale;
    u16 angle;
    BOOLEAN end_layer;
} HW_DEP_PROP;
#else
typedef struct hw_dep_property { 
    /* No hardware-dependent properties */ 
} HW_DEP_PROP;
#endif 


/*****************************************/
/*       Basic Graphic Component         */
/*****************************************/
typedef struct dot {
    u32 x;                     /* screen-relative position of x */
    u32 y;                     /* screen-relative position of y */
    u32 size;                  /* pixel size */
    COLOR *color;              /* color */
    BOOLEAN visible;           /* visible ? */
    BOOLEAN tp;                /* transparent ? */
    HW_DEP_PROP hw_dep_prop;   /* hardware-dependent properties */
} DOT;

typedef struct rect {
    u32 x;                     /* screen-relative position of x */
    u32 y;                     /* screen-relative position of y */
    u32 width;                 /* rectangle width */
    u32 height;                /* rectangle height */
    COLOR *color;              /* color */
    BOOLEAN filled;            /* filled rectangle ? */
    BOOLEAN visible;           /* visible ? */
    BOOLEAN tp;                /* transparent ? */
    HW_DEP_PROP hw_dep_prop;   /* hardware-dependent properties */
} RECT;

typedef struct line {
    u32 sx;                    /* screen-relative start position of x */
    u32 sy;                    /* screen-relative start position of y */
    u32 dx;                    /* screen-relative end position of x */
    u32 dy;                    /* screen-relative end position of y */
    COLOR *color;              /* color */
    BOOLEAN visible;           /* visible ? */
    BOOLEAN tp;                /* transparent ? */
    HW_DEP_PROP hw_dep_prop;   /* hardware-dependent properties */
} LINE;

typedef struct image {
    u32 x;                     /* screen-relative position of x */
    u32 y;                     /* screen-relative position of y */
    u32 width;                 /* image width */
    u32 height;                /* image height */
    u8 *data;	                 /* point to image data */
    BOOLEAN visible;           /* visible ? */
    BOOLEAN tp;                /* transparent ? */
    u8 opacity;                /* image opacity, value: 0 ~ 100 */
    u8 *opacified_data;        /* opacified image data */
    BOOLEAN opacify_noncache;  /* opacified data should be cached or not? */
    HW_DEP_PROP hw_dep_prop;   /* hardware-dependent properties */
} IMAGE;

typedef struct text {
    u32 x;                     /* screen-relative position of x */
    u32 y;                     /* screen-relative position of y */
    u32 size;                  /* text size for user */
    u32 txt_width;             /* text total width */
    u32 txt_height;            /* text height */
    COLOR *bg_color;           /* text background color */
    COLOR *fg_color;           /* text foreground color */
    unicode_t *string;         /* text unicode string */
    u32 txt_count;             /* text count of string */
    u32 *char_width;           /* text width for each character */
    u32 *char_height;          /* text height for each character */
    u8 **data;                 /* text raw data */
    u8 *font_file;             /* text font file */
    u32 font_size;             /* text fone size */
    u32 line_width;            /* text width per line, usually equal to WinObj width */
    u32 line_count;            /* line count, for multilines = false -> line_count = 1 */
    BOOLEAN multilines;        /* multi lines ? */
    BOOLEAN visible;           /* visible ? */
    BOOLEAN tp;                /* transparent ? */
    u8 opacity;                /* text opacity, value: 0 ~ 100 */
    BOOLEAN opacify_noncache;  /* opacified data should be cached or not? */
    HW_DEP_PROP hw_dep_prop;   /* hardware-dependent properties */
} TEXT;

int DrawDot(DOT *dot);
int DrawLine(LINE *line);
int DrawRect(RECT *rect);
int DrawImage(IMAGE *image);
int DrawText(TEXT *txt);
void GraphicFlush();
void GraphicScaleImage(IMAGE *image, s32 multiplier);
void GraphicScaleLine(LINE *line, s32 multiplier);
void GraphicScaleRect(RECT *rect, s32 multiplier);
inline void GraphicDeviceLockInit();
inline void GraphicDeviceLockDestroy();
inline void GraphicDeviceLock();
inline void GraphicDeviceUnlock();
IMAGE *CaptureImage(IMAGE *src, u32 x, u32 y, u32 w, u32 h, BOOLEAN which);
int OpacifyImage(IMAGE *fg, IMAGE *bg, int opacity);

#endif
